#include<iostream>
#include<memory>
#include<string>

// 简单工厂模式
// 抽象水果类
// class Fruit
// {
//     public:
//     Fruit(){}
//     virtual void product() = 0;
// };

// //派生类
// class Apple : public Fruit
// {
//     public:
//     Apple(){}
//     virtual void product()
//     {
//         std::cout<<"生产了一个苹果\n";
//     }
// };

// class Banana : public Fruit
// {
//     public:
//     Banana(){}
//     virtual void product()
//     {
//         std::cout<<"生产了一个香蕉\n";
//     }
// };

// //生产工厂类
// class Factory
// {   
//     public:
//     Factory(){}
//     ~Factory(){}
//     static std::shared_ptr<Fruit> factory(const std::string& res)
//     {
//         if(res == "苹果")
//         {
//             return std::make_shared<Apple>();   
//         }
//         else 
//         {
//             return std::make_shared<Banana>();
//         }
//         return std::shared_ptr<Fruit>(); //匿名对象
//     }
// };


// 工厂方法模式
// //水果抽象类
// class Fruit
// {
//     public:
//     virtual void product() = 0;
// };

// //水果派生类
// class Apple : public Fruit
// {
//     public:
//     virtual void product()
//     {
//         std::cout<<"生产一个苹果\n";
//     }
// };

// class Banana : public Fruit
// {
//     public:
//     virtual void product()
//     {
//         std::cout<<"生产一个香蕉\n";
//     }
// };

// //抽象工厂类
// class FruitFactory
// {
//     public:
//     virtual std::shared_ptr<Fruit> factory() = 0;
// };

// //工厂派生类
// class AppleFactory : public FruitFactory
// {
//     public:
//     virtual std::shared_ptr<Fruit> factory()
//     {
//         return std::make_shared<Apple>();
//     }
// };

// class BananaFactory : public FruitFactory
// {
//     public:
//     virtual std::shared_ptr<Fruit> factory()
//     {
//         return std::make_shared<Banana>();
//     }
// };


//抽象工厂模式
//水果抽象类
class Fruit
{
    public:
    virtual void product() = 0;
};

//水果派生类
class Apple : public Fruit
{
    public:
    virtual void product()
    {
        std::cout<<"生产一个苹果\n";
    }
};

class Banana : public Fruit
{
    public:
    virtual void product()
    {
        std::cout<<"生产一个香蕉\n";
    }
};

//抽象动物类
class Animal
{
    public:
    virtual void product() = 0;
};
//派生动物类
class Dog : public Animal
{
    public:
    virtual void product()
    {
        std::cout<<"生产一只狗\n";
    }
};
class Cat : public Animal
{
    public:
    virtual void product()
    {
        std::cout<<"生产一只猫\n";
    }
};

//抽象工厂类
class Factory
{
    public:
    virtual std::shared_ptr<Fruit> fruitfactory(const std::string& name) = 0;
    virtual std::shared_ptr<Animal> animalfactory(const std::string& name) = 0;
};

//水果工厂派生类
class FruitFactory : public Factory
{
    public:
    virtual std::shared_ptr<Animal> animalfactory(const std::string& name) {return std::shared_ptr<Animal>();}
    virtual std::shared_ptr<Fruit> fruitfactory(const std::string& name)
    {
        if(name == "苹果") return std::make_shared<Apple>();
        else return std::make_shared<Banana>();
        return std::shared_ptr<Fruit>();
    }
};
//动物工厂派生类
class AnimalFactory : public Factory
{
    public:
    virtual std::shared_ptr<Fruit> fruitfactory(const std::string& name) {return std::shared_ptr<Fruit>();}
    virtual std::shared_ptr<Animal> animalfactory(const std::string& name)
    {
        if(name == "狗") return std::make_shared<Dog>();
        else return std::make_shared<Cat>();
        return std::shared_ptr<Cat>();
    }
};

//超级工厂类
class SuperFactory
{
    public:
    static std::shared_ptr<Factory> create(const std::string& name)
    {
        if(name == "水果") return std::make_shared<FruitFactory>();
        else return std::make_shared<AnimalFactory>();
        return std::shared_ptr<Factory>();
    }
};



int main()
{
    // 简单工厂模式
    // std::shared_ptr<Factory> ft(new Factory);
    // std::shared_ptr<Fruit> fr = ft->factory("苹果");
    // fr->product();
    // fr = ft->factory("香蕉");
    // fr->product();

    //工厂方法模式
    // std::shared_ptr<FruitFactory> ft(new AppleFactory); 
    // auto fruit = ft->factory();
    // fruit->product();
    // ft.reset(new BananaFactory);
    // fruit = ft->factory();
    // fruit->product();

    //抽象工厂模式
    std::shared_ptr<Factory>ff = SuperFactory::create("水果");
    std::shared_ptr<Factory>af = SuperFactory::create("动物");
    std::shared_ptr<Fruit>f = ff->fruitfactory("苹果");
    f->product();
    std::shared_ptr<Animal>a = af->animalfactory("狗");
    a->product();
    f = ff->fruitfactory("香蕉");
    f->product();
    a = af->animalfactory("猫");
    a->product();
    return 0;
}